Make linked graphic register into LinkedManager again

Change-Id: I16b162f86d6221d120f6355f9a52c1abfcd0ac73
Reviewed-on: https://gerrit.libreoffice.org/52911
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
diff --git a/include/vcl/GraphicLoader.hxx b/include/vcl/GraphicLoader.hxx
index 9b96ec1..780de02e 100644
--- a/include/vcl/GraphicLoader.hxx
+++ b/include/vcl/GraphicLoader.hxx
@@ -16,6 +16,9 @@
{
namespace graphic
{
Graphic VCL_DLLPUBLIC loadFromURL(OUString const& rURL, sal_Int16 nExtWidth, sal_Int16 nExtHeight,
                                  sal_Int16 nExtMapMode);

Graphic VCL_DLLPUBLIC loadFromURL(OUString const& rURL);
}
} // end vcl::graphic
diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx
index c088e64..d69b9e8 100644
--- a/include/vcl/graph.hxx
+++ b/include/vcl/graph.hxx
@@ -33,6 +33,7 @@
#include <com/sun/star/uno/Reference.hxx>
#include <vcl/vectorgraphicdata.hxx>
#include <basegfx/vector/b2dsize.hxx>
#include <vcl/GraphicExternalLink.hxx>


enum class GraphicType
@@ -114,6 +115,7 @@

public:
                    Graphic();
                    Graphic( const GraphicExternalLink& rGraphicLink );
                    Graphic( const Graphic& rGraphic );
                    Graphic( Graphic&& rGraphic );
                    Graphic( const Bitmap& rBmp );
diff --git a/oox/source/drawingml/misccontexts.cxx b/oox/source/drawingml/misccontexts.cxx
index 583c9d7..ec321fb 100644
--- a/oox/source/drawingml/misccontexts.cxx
+++ b/oox/source/drawingml/misccontexts.cxx
@@ -27,6 +27,7 @@
#include <oox/token/tokens.hxx>
#include <sfx2/docfile.hxx>
#include <vcl/GraphicLoader.hxx>
#include <vcl/GraphicExternalLink.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
@@ -161,7 +162,8 @@
        // code rework.
        OUString aRelId = rAttribs.getString( R_TOKEN( link ), OUString() );
        OUString aTargetLink = getFilter().getAbsoluteUrl( getRelations().getExternalTargetFromRelId( aRelId ) );
        Graphic aGraphic = vcl::graphic::loadFromURL(aTargetLink);
        GraphicExternalLink aLink(aTargetLink);
        Graphic aGraphic(aLink);
        mrBlipProps.mxFillGraphic = aGraphic.GetXGraphic();
    }
}
diff --git a/sfx2/source/appl/fileobj.cxx b/sfx2/source/appl/fileobj.cxx
index f19e7f9..371d883 100644
--- a/sfx2/source/appl/fileobj.cxx
+++ b/sfx2/source/appl/fileobj.cxx
@@ -76,7 +76,7 @@

bool SvFileObject::GetData( css::uno::Any & rData,
                                const OUString & rMimeType,
                                bool bGetSynchron )
                                bool /*bGetSynchron*/ )
{
    SotClipboardFormatId nFmt = SotExchange::RegisterFormatMimeType( rMimeType );
    switch( nType )
@@ -92,101 +92,11 @@
        break;

    case FILETYPE_GRF:
        if( !bLoadError )
        if (SotClipboardFormatId::GDIMETAFILE == nFmt
         || SotClipboardFormatId::BITMAP == nFmt
         || SotClipboardFormatId::SVXB == nFmt)
        {
            tools::SvRef<SfxMedium> xTmpMed;

            if( SotClipboardFormatId::GDIMETAFILE == nFmt || SotClipboardFormatId::BITMAP == nFmt ||
                SotClipboardFormatId::SVXB == nFmt )
            {
                Graphic aGrf;

                // If the native format is requested, has to be reset at the
                // end of the flag. Is solely in the sw/ndgrf.cxx used when
                // the link is removed form GraphicNode.
                bool bOldNativFormat = bNativFormat;

                // If about to print, waiting for the data to be available
                if( bGetSynchron )
                {
                    // call a LoadFile every second time to test the loading
                    if( !xMed.is() )
                        LoadFile_Impl();

                    if( !bInCallDownload )
                    {
                        xTmpMed = xMed;
                        while( bWaitForData )
                            Application::Reschedule();

                        xMed = xTmpMed;
                        bClearMedium = true;
                    }
                }

                if( !bWaitForData && ( xMed.is() ||  // was loaded as URL
                      ( bSynchron && LoadFile_Impl() && xMed.is() ) ) )
                {
                    // If it was loaded from the Internet, do not retry
                    if( !bGetSynchron )
                        bLoadAgain = !xMed->IsRemote();
                    bLoadError = !GetGraphic_Impl( aGrf, xMed->GetInStream() );
                }
                else if( !LoadFile_Impl() ||
                        !GetGraphic_Impl( aGrf, xMed.is() ? xMed->GetInStream() : nullptr ))
                {
                    if( !xMed.is() )
                        break;
                    aGrf.SetDefaultType();
                }

                if( SotClipboardFormatId::SVXB != nFmt )
                    nFmt = (bLoadError || GraphicType::Bitmap == aGrf.GetType())
                                ? SotClipboardFormatId::BITMAP
                                : SotClipboardFormatId::GDIMETAFILE;

                SvMemoryStream aMemStm( 0, 65535 );
                switch ( nFmt )
                {
                case SotClipboardFormatId::SVXB:
                    if( GraphicType::NONE != aGrf.GetType() )
                    {
                        aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
                        WriteGraphic( aMemStm, aGrf );
                    }
                    break;

                case SotClipboardFormatId::BITMAP:
                {
                    const Bitmap aBitmap(aGrf.GetBitmap());

                    if(!aBitmap.IsEmpty())
                    {
                        WriteDIB(aBitmap, aMemStm, false, true);
                    }

                    break;
                }

                default:
                    if( aGrf.GetGDIMetaFile().GetActionSize() )
                    {
                        GDIMetaFile aMeta( aGrf.GetGDIMetaFile() );
                        aMeta.Write( aMemStm );
                    }
                }
                rData <<= css::uno::Sequence< sal_Int8 >( static_cast<sal_Int8 const *>(aMemStm.GetData()),
                                        aMemStm.Seek( STREAM_SEEK_TO_END ) );

                bNativFormat = bOldNativFormat;

                // Everything ready?
                if( xMed.is() && !bSynchron && bClearMedium )
                {
                    xMed.clear();
                    bClearMedium = false;
                }
            }
            rData <<= sFileNm;
        }
        break;
    case FILETYPE_OBJECT:
diff --git a/sfx2/source/appl/linkmgr2.cxx b/sfx2/source/appl/linkmgr2.cxx
index 9ca22e8..64e89a9 100644
--- a/sfx2/source/appl/linkmgr2.cxx
+++ b/sfx2/source/appl/linkmgr2.cxx
@@ -40,6 +40,7 @@
#include <sfx2/request.hxx>
#include <vcl/dibtools.hxx>
#include <unotools/charclass.hxx>
#include <vcl/GraphicLoader.hxx>

#include "fileobj.hxx"
#include "impldde.hxx"
@@ -498,12 +499,26 @@

bool LinkManager::GetGraphicFromAny( const OUString& rMimeType,
                                const css::uno::Any & rValue,
                                Graphic& rGrf )
                                Graphic& rGraphic )
{
    bool bRet = false;
    css::uno::Sequence< sal_Int8 > aSeq;
    if( rValue.hasValue() && ( rValue >>= aSeq ) )

    if (!rValue.hasValue())
        return bRet;

    if (rValue.has<OUString>())
    {
        OUString sURL = rValue.get<OUString>();
        rGraphic = vcl::graphic::loadFromURL(sURL);
        if (!rGraphic)
            rGraphic.SetDefaultType();
        rGraphic.setOriginURL(sURL);
        return true;
    }
    else if (rValue.has<css::uno::Sequence<sal_Int8>>())
    {
        auto aSeq = rValue.get<css::uno::Sequence<sal_Int8>>();

        SvMemoryStream aMemStm( const_cast<sal_Int8 *>(aSeq.getConstArray()), aSeq.getLength(),
                                StreamMode::READ );
        aMemStm.Seek( 0 );
@@ -512,7 +527,7 @@
        {
        case SotClipboardFormatId::SVXB:
            {
                ReadGraphic( aMemStm, rGrf );
                ReadGraphic( aMemStm, rGraphic );
                bRet = true;
            }
            break;
@@ -520,7 +535,7 @@
            {
                GDIMetaFile aMtf;
                aMtf.Read( aMemStm );
                rGrf = aMtf;
                rGraphic = aMtf;
                bRet = true;
            }
            break;
@@ -528,7 +543,7 @@
            {
                Bitmap aBmp;
                ReadDIB(aBmp, aMemStm, true);
                rGrf = aBmp;
                rGraphic = aBmp;
                bRet = true;
            }
            break;
diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx
index 21412a2..930569c 100644
--- a/svx/source/svdraw/svdograf.cxx
+++ b/svx/source/svdraw/svdograf.cxx
@@ -102,6 +102,7 @@
        // that it is a SVG graphic, but only because no one yet tried to interpret it.
        rGF.ImportGraphic( aGraphic, aFileName, *pInStrm, nFilter, nullptr, GraphicFilterImportFlags::NONE, &aFilterData );
    }
    aGraphic.setOriginURL(aFileName);
    return aGraphic;
}

@@ -227,8 +228,7 @@
        Graphic aGraphic;
        if( sfx2::LinkManager::GetGraphicFromAny( rMimeType, rValue, aGraphic ))
        {
               rGrafObj.NbcSetGraphic( aGraphic );
            rGrafObj.ActionChanged();
            rGrafObj.ImpSetLinkedGraphic(aGraphic);
        }
        else if( SotExchange::GetFormatIdFromMimeType( rMimeType ) != sfx2::LinkManager::RegisterStatusInfoId() )
        {
@@ -278,7 +278,6 @@
    return new sdr::contact::ViewContactOfGraphic(*this);
}


// check if SVG and if try to get ObjectInfoPrimitive2D and extract info

void SdrGrafObj::onGraphicChanged()
@@ -426,7 +425,6 @@
{
    if (bForceSwapIn)
        ForceSwapIn();

    return *mpGraphicObject.get();
}

@@ -460,15 +458,29 @@
    onGraphicChanged();
}

void SdrGrafObj::SetGraphic( const Graphic& rGrf )
void SdrGrafObj::SetGraphic( const Graphic& rGraphic )
{
    NbcSetGraphic(rGrf);
    if (!rGraphic.getOriginURL().isEmpty())
    {
        ImpDeregisterLink();
        aFileName = rGraphic.getOriginURL();
        aReferer = "";
        aFilterName = "";
    }
    NbcSetGraphic(rGraphic);
    if (!rGraphic.getOriginURL().isEmpty())
    {
        ImpRegisterLink();
        mpGraphicObject->SetUserData();
    }
    SetChanged();
    BroadcastObjectChange();
    ForceSwapIn();
}

const Graphic& SdrGrafObj::GetGraphic() const
{
    ForceSwapIn();
    return mpGraphicObject->GetGraphic();
}

@@ -597,9 +609,13 @@
    return aSize;
}

// TODO Remove
void SdrGrafObj::ForceSwapIn() const
{
    if (pGraphicLink && (mpGraphicObject->GetType() == GraphicType::NONE  ||
                         mpGraphicObject->GetType() == GraphicType::Default) )
    {
        pGraphicLink->Update();
    }
}

void SdrGrafObj::ImpRegisterLink()
@@ -630,15 +646,11 @@
    }
}

void SdrGrafObj::SetGraphicLink(const OUString& rFileName, const OUString& rReferer, const OUString& rFilterName)
void SdrGrafObj::SetGraphicLink(const OUString& rFileName, const OUString& /*rReferer*/, const OUString& /*rFilterName*/)
{
    ImpDeregisterLink();
    aFileName = rFileName;
    aReferer = rReferer;
    aFilterName = rFilterName;
    ImpRegisterLink();
    mpGraphicObject->SetUserData();
    SetGraphic(vcl::graphic::loadFromURL(aFileName));
    Graphic aGraphic;
    aGraphic.setOriginURL(rFileName);
    SetGraphic(aGraphic);
}

void SdrGrafObj::ReleaseGraphicLink()
@@ -862,6 +874,7 @@
    // temporary interaction object and load graphic
    if(pRetval && IsLinkedGraphic())
    {
        pRetval->ForceSwapIn();
        pRetval->ReleaseGraphicLink();
    }

diff --git a/sw/source/core/graphic/ndgrf.cxx b/sw/source/core/graphic/ndgrf.cxx
index d9adeb0..a046085b 100644
--- a/sw/source/core/graphic/ndgrf.cxx
+++ b/sw/source/core/graphic/ndgrf.cxx
@@ -73,11 +73,19 @@
    mbLinkedInputStreamReady( false ),
    mbIsStreamReadOnly( false )
{
    OUString sURLLink(pGraphic->getOriginURL());
    if (sURLLink.isEmpty() && !rGrfName.isEmpty())
    {
        sURLLink = rGrfName;
        Graphic aGraphic(*pGraphic);
        aGraphic.setOriginURL(sURLLink);
    }

    bInSwapIn = bChgTwipSize =
        bFrameInPaint = bScaleImageMap = false;

    bGraphicArrived = true;
    ReRead(rGrfName, rFltName, pGraphic, nullptr, false);
    ReRead(sURLLink, rFltName, pGraphic, nullptr, false);
}

SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
@@ -472,9 +480,52 @@
 * @return true if ReRead or reading successful,
 *         false if not loaded
 */
bool SwGrfNode::SwapIn( bool /*bWaitForData*/ )
bool SwGrfNode::SwapIn(bool bWaitForData)
{
    return true;
    if(bInSwapIn) // not recursively!
        return true;

    bool bRet = false;
    bInSwapIn = true;
    SwBaseLink* pLink = static_cast<SwBaseLink*>( refLink.get() );

    if( pLink )
    {
        if( GraphicType::NONE == maGrfObj.GetType() ||
            GraphicType::Default == maGrfObj.GetType() )
        {
            // link was not loaded yet
            if( pLink->SwapIn( bWaitForData ) )
            {
                bRet = true;
            }
            else if( GraphicType::Default == maGrfObj.GetType() )
            {
                // no default bitmap anymore, thus re-paint
                delete mpReplacementGraphic;
                mpReplacementGraphic = nullptr;

                maGrfObj.SetGraphic( Graphic() );
                onGraphicChanged();
                SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
                ModifyNotification( &aMsgHint, &aMsgHint );
            }
        }
        else
        {
            bRet = true;
        }
    }
    else
        bRet = true;

    if (bRet)
    {
        if( !nGrfSize.Width() && !nGrfSize.Height() )
            SetTwipSize( ::GetGraphicSizeTwip( maGrfObj.GetGraphic(), nullptr ) );
    }
    bInSwapIn = false;
    return bRet;
}

bool SwGrfNode::SwapOut()
diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
index c5c0717..119f176 100644
--- a/sw/source/uibase/uiview/view2.cxx
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -265,7 +265,7 @@

                OUString sURL = URIHelper::SmartRel2Abs(
                    aTemp, rPath, URIHelper::GetMaybeFileHdl() );

                aGraphic.setOriginURL(sURL);
                rShell.Insert( sURL, rFilter, aGraphic, &aFrameManager );
            }
            else
diff --git a/vcl/inc/graphic/Manager.hxx b/vcl/inc/graphic/Manager.hxx
index ec376153..4b45852 100644
--- a/vcl/inc/graphic/Manager.hxx
+++ b/vcl/inc/graphic/Manager.hxx
@@ -17,6 +17,7 @@
#include <vcl/vectorgraphicdata.hxx>
#include <vcl/metaact.hxx>
#include <vcl/timer.hxx>
#include <vcl/GraphicExternalLink.hxx>

#include <officecfg/Office/Common.hxx>
#include <unotools/configmgr.hxx>
@@ -62,6 +63,7 @@
    std::shared_ptr<ImpGraphic> newInstance(const VectorGraphicDataPtr& rVectorGraphicDataPtr);
    std::shared_ptr<ImpGraphic> newInstance(const Animation& rAnimation);
    std::shared_ptr<ImpGraphic> newInstance(const GDIMetaFile& rMtf);
    std::shared_ptr<ImpGraphic> newInstance(const GraphicExternalLink& rGraphicLink);
};
}
} // end namespace vcl::graphic
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index cdc747e..91dcad7 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -31,6 +31,8 @@
#include <com/sun/star/graphic/XGraphic.hpp>
#include <cppuhelper/typeprovider.hxx>
#include <graphic/UnoGraphic.hxx>
#include <vcl/GraphicExternalLink.hxx>


using namespace ::com::sun::star;

@@ -199,6 +201,11 @@
{
}

Graphic::Graphic(GraphicExternalLink const & rGraphicExternalLink)
    : mxImpGraphic(vcl::graphic::Manager::get().newInstance(rGraphicExternalLink))
{
}

Graphic::Graphic(const Bitmap& rBmp)
    : mxImpGraphic(vcl::graphic::Manager::get().newInstance(rBmp))
{
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 13f09ee..0f1e849 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -226,6 +226,16 @@
    rImpGraphic.mbDummyContext = false;
}

ImpGraphic::ImpGraphic(GraphicExternalLink const & rGraphicExternalLink) :
        meType          ( GraphicType::Default ),
        mnSizeBytes     ( 0 ),
        mbSwapOut       ( false ),
        mbDummyContext  ( false ),
        maGraphicExternalLink(rGraphicExternalLink),
        maLastUsed (std::chrono::high_resolution_clock::now())
{
}

ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
        maEx            ( rBitmap ),
        meType          ( !rBitmap.IsEmpty() ? GraphicType::Bitmap : GraphicType::NONE ),
diff --git a/vcl/source/graphic/GraphicLoader.cxx b/vcl/source/graphic/GraphicLoader.cxx
index b07b345..9c453ac 100644
--- a/vcl/source/graphic/GraphicLoader.cxx
+++ b/vcl/source/graphic/GraphicLoader.cxx
@@ -10,11 +10,9 @@

#include <vcl/GraphicLoader.hxx>

#include <comphelper/processfactory.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/graphic/GraphicProvider.hpp>
#include <com/sun/star/graphic/XGraphicProvider.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
#include <unotools/ucbstreamhelper.hxx>
#include <vcl/graphicfilter.hxx>
#include <vcl/wmf.hxx>

using namespace css;

@@ -22,35 +20,38 @@
{
namespace graphic
{
Graphic loadFromURL(OUString const& rURL)
Graphic loadFromURL(OUString const& rURL, sal_Int16 nExtWidth, sal_Int16 nExtHeight,
                    sal_Int16 nExtMapMode)
{
    // Define APM Header if goal height and width are defined
    WmfExternal aExtHeader;
    aExtHeader.xExt = nExtWidth;
    aExtHeader.yExt = nExtHeight;
    aExtHeader.mapMode = nExtMapMode;
    WmfExternal* pExtHeader = nullptr;
    if (nExtMapMode > 0)
        pExtHeader = &aExtHeader;

    Graphic aGraphic;

    try
    std::unique_ptr<SvStream> pInputStream;
    pInputStream.reset(utl::UcbStreamHelper::CreateStream(rURL, StreamMode::READ));

    if (pInputStream)
    {
        uno::Reference<css::graphic::XGraphic> xGraphic;
        uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
        uno::Reference<css::graphic::XGraphicProvider> xProvider;
        xProvider.set(css::graphic::GraphicProvider::create(xContext));
        GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();

        uno::Sequence<beans::PropertyValue> aLoadProps(1);
        aLoadProps[0].Name = "URL";
        aLoadProps[0].Value <<= rURL;

        xGraphic = xProvider->queryGraphic(aLoadProps);

        if (xGraphic.is())
            aGraphic = Graphic(xGraphic);
        else
            aGraphic.SetDefaultType();
        aGraphic.setOriginURL(rURL);
    }
    catch (uno::Exception const&)
    {
        ErrCode nError
            = rFilter.ImportGraphic(aGraphic, rURL, *pInputStream, GRFILTER_FORMAT_DONTKNOW,
                                    nullptr, GraphicFilterImportFlags::NONE, pExtHeader);
        if (nError != ERRCODE_NONE || aGraphic.GetType() == GraphicType::NONE)
            return Graphic();
    }

    return aGraphic;
}

Graphic loadFromURL(OUString const& rURL) { return loadFromURL(rURL, 0, 0, 0); }
}
} // end vcl::graphic

diff --git a/vcl/source/graphic/Manager.cxx b/vcl/source/graphic/Manager.cxx
index ee161c2..549b9c6 100644
--- a/vcl/source/graphic/Manager.cxx
+++ b/vcl/source/graphic/Manager.cxx
@@ -179,6 +179,13 @@
    return pReturn;
}

std::shared_ptr<ImpGraphic> Manager::newInstance(const GraphicExternalLink& rGraphicLink)
{
    auto pReturn = std::make_shared<ImpGraphic>(rGraphicLink);
    registerGraphic(pReturn, "GraphicExternalLink");
    return pReturn;
}

void Manager::swappedIn(const ImpGraphic* pImpGraphic)
{
    mnUsedSize += pImpGraphic->ImplGetSizeBytes();
diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx
index 6adabad..7a08b56 100644
--- a/xmloff/source/core/xmlimp.cxx
+++ b/xmloff/source/core/xmlimp.cxx
@@ -62,6 +62,7 @@
#include <unotools/fontcvt.hxx>
#include <o3tl/make_unique.hxx>
#include <xmloff/fasttokenhandler.hxx>
#include <vcl/GraphicExternalLink.hxx>

#include <com/sun/star/rdf/XMetadatable.hpp>
#include <com/sun/star/rdf/XRepositorySupplier.hpp>
@@ -1370,19 +1371,10 @@
        }
        else
        {
            uno::Reference<graphic::XGraphicProvider> xProvider(graphic::GraphicProvider::create(GetComponentContext()));
            OUString const & rAbsoluteURL = GetAbsoluteReference(rURL);
            uno::Sequence<beans::PropertyValue> aLoadProperties(comphelper::InitPropertySequence(
            {
                { "URL", uno::makeAny(rAbsoluteURL) }
            }));

            xGraphic = xProvider->queryGraphic(aLoadProperties);
            if (xGraphic.is())
            {
                Graphic aGraphic(xGraphic);
                aGraphic.setOriginURL(rAbsoluteURL);
            }
            GraphicExternalLink aExternalLink(rAbsoluteURL);
            Graphic aGraphic(aExternalLink);
            xGraphic = aGraphic.GetXGraphic();
        }
    }